﻿using System;
using System.ComponentModel;

namespace ExFlash.Actions
{
    public enum ActionCodes : byte
    {
        ActionNextFrame = 0x04,
        ActionPrevFrame = 0x05,
        ActionPlay = 0x06,
        ActionStop = 0x07,
        ActionToggleQuality = 0x08,
        ActionStopSounds = 0x09,
        ActionAdd = 0x0A,
        ActionSubtract = 0x0B,
        ActionMultiply = 0x0C,
        ActionDivide = 0x0D,
        ActionEquals = 0x0E,
        ActionLess = 0x0F,
        ActionAnd = 0x10,
        ActionOr = 0x11,
        ActionNot = 0x12,
        ActionStringEquals = 0x13,
        ActionStringLength = 0x14,
        ActionStringExtract = 0x15,
        ActionPop = 0x17,
        ActionToInteger = 0x18,
        ActionGetVariable = 0x1C,
        ActionSetVariable = 0x1D,
        ActionSetTarget2 = 0x20,
        ActionStringAdd = 0x21,
        ActionGetProperty = 0x22,
        ActionSetProperty = 0x23,
        ActionCloneSprite = 0x24,
        ActionRemoveSprite = 0x25,
        ActionTrace = 0x26,
        ActionStartDrag = 0x27,
        ActionEndDrag = 0x28,
        ActionStringLess = 0x29,
        ActionThrow = 0x2A,
        ActionCastOp = 0x2B,
        ActionImplementsOp = 0x2C,
        ActionRandomNumber = 0x30,
        ActionMbStringLength = 0x31,
        ActionCharToAscii = 0x32,
        ActionAsciiToChar = 0x33,
        ActionGetTime = 0x34,
        ActionMbStringExtract = 0x35,
        ActionMbCharToAscii = 0x36,
        ActionMbAsciiToChar = 0x37,
        ActionDelete = 0x3A,
        ActionDelete2 = 0x3B,
        ActionDefineLocal = 0x3C,
        ActionCallFunction = 0x3D,
        ActionReturn = 0x3E,
        ActionModulo = 0x3F,
        ActionNewObject = 0x40,
        ActionDefineLocal2 = 0x41,
        ActionInitArray = 0x42,
        ActionInitObject = 0x43,
        ActionTypeOf = 0x44,
        ActionTargetPath = 0x45,
        ActionEnumerate = 0x46,
        ActionAdd2 = 0x47,
        ActionLess2 = 0x48,
        ActionEquals2 = 0x49,
        ActionToNumber = 0x4A,
        ActionToString = 0x4B,
        ActionPushDuplicate = 0x4C,
        ActionStackSwap = 0x4D,
        ActionGetMember = 0x4E,
        ActionSetMember = 0x4F,
        ActionIncrement = 0x50,
        ActionDecrement = 0x51,
        ActionCallMethod = 0x52,
        ActionNewMethod = 0x53,
        ActionInstanceOf = 0x54,
        ActionEnumerate2 = 0x55,
        ActionBitAnd = 0x60,
        ActionBitOr = 0x61,
        ActionBitXor = 0x62,
        ActionBitLshift = 0x63,
        ActionBitRshift = 0x64,
        ActionBitURShift = 0x65,
        ActionStrictEquals = 0x66,
        ActionGreater = 0x67,
        ActionStringGreater = 0x68,
        ActionExtends = 0x69,
        ActionGoToFrame = 0x81,
        ActionGetUrl = 0x83,
        ActionStoreRegister = 0x87,
        ActionConstantPool = 0x88,
        ActionWaitForFrame = 0x8A,
        ActionSetTarget = 0x8B,
        ActionGoToLabel = 0x8C,
        ActionWaitForFrame2 = 0x8D,
        ActionDefineFunction2 = 0x8E,
        ActionTry = 0x8F,
        ActionWith = 0x94,
        ActionPush = 0x96,
        ActionJump = 0x99,
        ActionGetUrl2 = 0x9A,
        ActionDefineFunction = 0x9B,
        ActionIf = 0x9D,
        ActionCall = 0x9E,
        ActionGoToFrame2 = 0x9F
    }

    [TypeConverter(typeof(ExpandableObjectConverter))]
    public abstract class ActionRecord : ISwfSerializable
    {
        public Byte ActionCode
        {
            get;
            private set;
        }

        public ushort Length
        {
            get;
            protected set;
        }

        protected ActionRecord(Byte code)
        {
            if (code >= 0x80)
            {
                throw new ArgumentException("Received code above 0x80. Must use constructor with length parameter.", "code");
            }

            ActionCode = code;
        }

        protected ActionRecord(Byte code, ushort len)
        {
            if (code >= 0x80)
            {
                Length = len;
            }

            ActionCode = code;
        }
        
        #region ISwfSerializable Members

        public abstract void SwfDeserialize(BinaryBitReader reader);

        public abstract void SwfSerialize(byte[] arr, ref int offset);

        #endregion
    }
}
